package application;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.sql.SQLException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.dsrg.soenea.application.servlet.dispatcher.Dispatcher;
import org.dsrg.soenea.application.servlet.dispatcher.HttpServletHelper;
import org.dsrg.soenea.service.MySQLConnectionFactory;
import org.dsrg.soenea.service.registry.Registry;
import org.dsrg.soenea.service.threadLocal.DbRegistry;
import org.dsrg.soenea.service.threadLocal.ThreadLocalTracker;
import org.dsrg.soenea.uow.MapperFactory;
import org.dsrg.soenea.uow.UoW;

import domain.model.group.Group;
import domain.model.group.IGroup;
import domain.model.group.mapper.GroupOutputMapper;
import domain.model.invite.Invite;
import domain.model.invite.mapper.InviteOutputMapper;
import domain.model.person.Person;
import domain.model.person.mapper.PersonOutputMapper;
import domain.model.requestInvite.RequestInvite;
import domain.model.requestInvite.mapper.RequestInviteOutputMapper;
import domain.model.user.User;
import domain.model.user.mapper.UserOutputMapper;



public class FrontController extends HttpServlet 
{
	private static final long serialVersionUID = 1L;
	private final String DEFAULT_COMMAND = "login";
	
	public void init() throws ServletException 
	{
		super.init();
		prepareDbRegistry("");
	}
	
	public static void prepareDbRegistry(String db_id) 
	{
		MySQLConnectionFactory f = new MySQLConnectionFactory(null, null, null, null);
		try {
			f.defaultInitialization(db_id);
		} catch (SQLException e2) {
			e2.printStackTrace();
		}
		DbRegistry.setConFactory(db_id, f);
		String tablePrefix;
		try {
			tablePrefix = Registry.getProperty(db_id+"mySqlTablePrefix");
		} catch (Exception e1) {
			e1.printStackTrace();
			tablePrefix = "";
		}
		if(tablePrefix == null) {
			tablePrefix = "";
		}
		DbRegistry.setTablePrefix(db_id, tablePrefix);
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		doGet(request, response);
	}
	
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		preProcessRequest(request, response);
		try {
			processRequest(request, response);
		} finally {
			postProcessRequest(request, response);
		}
	}
	
	protected void preProcessRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{	
		try
		{
			// START TRANSACTION.
			DbRegistry.getDbConnection().createStatement().execute("START TRANSACTION;");
			
			// prep UoW
			UoW.newCurrent();
			MapperFactory mFac = new MapperFactory();
			
			// add mapping to the factory (for each Input/Output Mapper)
			 mFac.addMapping(Group.class, GroupOutputMapper.class);
			 mFac.addMapping(User.class, UserOutputMapper.class);
			 mFac.addMapping(Invite.class, InviteOutputMapper.class);
			 mFac.addMapping(Person.class, PersonOutputMapper.class);
			 mFac.addMapping(RequestInvite.class, RequestInviteOutputMapper.class);
			 
			UoW.initMapperFactory(mFac);
		}
		
		catch (Exception e)
		{
			
		}
	}
	
	protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		request.getSession().setMaxInactiveInterval(1200);
		
		//DEBUG
		//System.out.println("Printing the request URL: " + request.getRequestURL());
		
		//check if logged in.
		if(request.getSession().getAttribute("userid")==null)
		{
			if( ((String) request.getAttribute("command")).equalsIgnoreCase("home") )
			{
				request.getRequestDispatcher("/WEB-INF/JSP/home.jsp").forward(request, response);
				return;
			}
			
			request.setAttribute("command", "Login");  // not logged in-->send to login dispatcher
		}

		Dispatcher disp = getDispatcher(request);
		
		if(disp != null) 
		{
			disp.init(request, response);
			disp.execute();
		}
		else
		{
			// TODO: error message "Invalid Command"
		}
		
	}
	
	private Dispatcher getDispatcher(HttpServletRequest request) 
	{
		try {
			String command = (String) request.getAttribute("command");
			if (command == null)
				command = request.getParameter("command");
			if (command == null || command.isEmpty()) {
				return null;
			}
			String fqCommand = "application.dispatcher."
					+ command + "Dispatcher";
			return (Dispatcher) Class.forName(fqCommand).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	
	protected void postProcessRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		try 
		{
			//UoW.getCurrent().commit();
			DbRegistry.getDbConnection().createStatement().execute("COMMIT;");
			DbRegistry.closeDbConnectionIfNeeded();
		} 
		catch (Exception e) {}
		
		ThreadLocalTracker.purgeThreadLocal();
	}
	
	
}
